<template>
    <a-form :label-col="labelCol">
        <template v-for="item in ViewConfig">
            <div class="Title">{{ item.title }}</div>
            <template v-for="child in item.children" :key="child.Key">
                <ObjectItem :ref="setRef" v-if="isEnable(child)" :Level="Level" :Option="child" :Model="Model"
                    :Value="Value" @UpdateValue="UpdateValue" />
            </template>
        </template>
    </a-form>
</template>
<script setup>
import { onMounted, watch, provide, ref, nextTick } from 'vue';
import ObjectItem from './ObjectItem.vue';
import * as Util from '../Util'
import { StringToRule, GetChangeValueEvents, GetParamsMapping, GetDictMapping, GetChangeOptionEvents } from '../Util'


const props = defineProps(['Model', 'Level', 'DefaultValue']);
const ViewConfig = ref([]);


const labelCol = ref({ style: { width: '100px' } });

const ChangeEvents = GetChangeValueEvents(props.Model.Param);
const OptionChangeEvents = GetChangeOptionEvents(props.Model.Param);
const ParamsMapping = ref(GetParamsMapping(props.Model.Param));

const Value = ref(Util.FormatValue(props.Model.Param, props.DefaultValue));
ViewConfig.value = Util.GetDefaultFormView(ParamsMapping.value, props.Model.View.Form.Default)

const _Refs = {};
const setRef = (el) => {
    el && (_Refs[el.Key] = el);
}
const isEnable = (Option) => {
    if (Option.Event && Option.Event.Enable) {
        return StringToRule(Option.Event.Enable, Value.value)
    } else {
        return true
    }
};

// 处理 Options 改变事件
const SetOptions = function (val) {
    for (const key in OptionChangeEvents) {
        const EventMapping = OptionChangeEvents[key];
        for (const Itemkey in EventMapping) {
            const element = EventMapping[Itemkey];
            if (StringToRule(Itemkey, val)) {
                var _ItemOption = ParamsMapping.value[key];
                for (const key in element) {
                    const item = element[key];
                    switch (key) {
                        case 'Label':
                            _ItemOption.Label = item
                            break;
                        case 'readonly':
                            _ItemOption.readonly = item
                            break;
                        case 'required':
                            if (!_ItemOption.Rule) {
                                _ItemOption.Rule = {};
                            }
                            _ItemOption.Rule.required = item
                            break;
                    }
                };
            }
        }
    };
}

// 处理值绑定事件
watch(Value, val => {
    for (const key in ChangeEvents) {
        const EventMapping = ChangeEvents[key];
        for (const Itemkey in EventMapping) {
            const element = EventMapping[Itemkey];
            if (StringToRule(Itemkey, val)) {
                Value.value[key] = element
            }
        }
    };
    val && SetOptions(val);
}, { deep: true });
function UpdateValue(key, value) {
    Value.value[key] = value;
}

// 处理Select 多级联动
const DictMapping = GetDictMapping(props.Model.Param);
const UpdateSelectDict = function (key) {
    if (DictMapping[key] && _Refs[key]) {
        const Dict = _Refs[key].ObjItem.GetValueObject();
        for (const ToKey in DictMapping[key]) {
            const ToObj = DictMapping[key][ToKey];
            if (_Refs[ToKey] && _Refs[ToKey].ObjItem) {
                var _value = null;
                if (ToObj.Default != 'null' && Dict[ToObj.Key] && Dict[ToObj.Key][ToObj.Default]) {
                    _value = Dict[ToObj.Key][ToObj.Default].value;
                }
                _Refs[ToKey].ObjItem.SetDictValue(Dict[ToObj.Key], _value);
            }
        }
    }
}

provide('UpdateSelectDict', UpdateSelectDict)
onMounted(() => {
    nextTick(() => {
        for (const key in DictMapping) {
            UpdateSelectDict(key);
        }
    })
})

const TypeArray = ['String', 'Int', 'Number', 'Select'];
const GetValue = function () {
    var _data = JSON.parse(JSON.stringify(Value.value));
    for (const key in ParamsMapping.value) {
        const element = ParamsMapping.value[key];
        if (!TypeArray.includes(element.Type) && _Refs[element.Key]) {
            _data[key] = _Refs[element.Key].ObjItem.GetValue();
        }
    }
    return _data
}

const SetValue = function () { }


defineExpose({ GetValue, SetValue })



</script>
<style lang="less" scoped>
.Title {
    padding: 4px 15px;
    font-size: 16px;
    border-bottom: 1px solid #CCC;
    margin-bottom: 10px;
}
</style>